/**
 * 计算校验和（低8位）
 * @param {number[]} bytes - 不包含校验字节的数据
 * @returns {number} 校验和
 */
export function calcChecksum(bytes: number[]) {
  return bytes.reduce((sum, b) => sum + b, 0) & 0xff;
}

/**
 * 构建数据包
 * @param {number} cmd 指令
 * @param {number[]} data 数据区（默认 30 字节，不够补 0x00）
 * @returns {number[]} 完整数据包
 */
export function buildPacket(cmd: number, data: number[] = []) {
  const header = [0xaa, 0x55];
  const payload = Array.from({ length: 30 }, (_, i) => data[i] ?? 0x00);
  const body = [...header, cmd, ...payload];
  const checksum = calcChecksum(body);
  return [...body, checksum];
}

/**
 * 解析数据包
 * @param {number[]} packet 完整数据包
 * @returns {object} 解析结果
 */
export function parsePacket(packet: number[]) {
  if (packet[0] !== 0xaa || packet[1] !== 0x55) {
    throw new Error("协议头错误");
  }
  const cmd = packet[2];
  const data = packet.slice(3, -1);
  const checksum = packet[packet.length - 1];
  const valid = calcChecksum(packet.slice(0, -1)) === checksum;

  return {
    cmd,
    data,
    checksum,
    valid,
  };
}

/**
 * 将字符串转成 28 字节数组（ASCII/UTF-8 编码）
 * @param {string} str - 输入字符串（微信ID等）
 * @returns {number[]} 长度为 28 的字节数组
 */
export function stringTo28Bytes(str: string) {
  const bytes = [];
  for (let i = 0; i < str.length && i < 28; i++) {
    bytes.push(str.charCodeAt(i) & 0xff); // 取低8位
  }
  while (bytes.length < 28) {
    bytes.push(0x00); // 不足补 0
  }
  return bytes;
}

/**
 * UniApp 蓝牙管理器单例类
 * 将 UniApp 蓝牙 API 的回调函数转换为 Promise
 */
class BluetoothManager {
  private static instance: BluetoothManager;
  private isInitialized = false;
  private connectedDeviceId = "";
  private devices: UniApp.BluetoothDeviceInfo[] = [];
  private isScanning = false;
  private scanTimeout = 3 * 1000;
  private constructor() {
    this.openBluetoothAdapter();
  }
  serviceId = "";
  characteristicId = "";
  /**
   * 获取单例实例
   */
  static getInstance(): BluetoothManager {
    if (!BluetoothManager.instance) {
      BluetoothManager.instance = new BluetoothManager();
    }
    return BluetoothManager.instance;
  }
  getDevices(): UniApp.BluetoothDeviceInfo[] {
    return this.devices;
  }
  getIsScanning(): boolean {
    return this.isScanning;
  }
  startScanning(): Promise<UniApp.GetBluetoothDevicesSuccess["devices"]> {
    return new Promise((resolve, reject) => {
      setTimeout(async () => {
        this.isScanning = false;
        try {
          await bluetoothManager.stopBluetoothDevicesDiscovery();
          const { devices } = await bluetoothManager.getBluetoothDevices();
          resolve(devices);
        } catch (error) {
          reject(error);
        }
      }, this.scanTimeout);
      this.startBluetoothDevicesDiscovery().catch(reject);
    });
  }
  /**
   * 初始化蓝牙适配器
   */
  openBluetoothAdapter(): Promise<void> {
    return new Promise((resolve, reject) => {
      uni.openBluetoothAdapter({
        success: () => {
          this.isInitialized = true;
          resolve();
        },
        fail: (error) => {
          reject(new Error(`蓝牙初始化失败: ${error.errMsg}`));
        },
      });
    });
  }

  /**
   * 关闭蓝牙适配器
   */
  closeBluetoothAdapter(): Promise<void> {
    return new Promise((resolve, reject) => {
      uni.closeBluetoothAdapter({
        success: () => {
          this.isInitialized = false;
          this.connectedDeviceId = "";
          resolve();
        },
        fail: (error) => {
          reject(new Error(`关闭蓝牙适配器失败: ${error.errMsg}`));
        },
      });
    });
  }

  /**
   * 获取蓝牙适配器状态
   */
  getBluetoothAdapterState(): Promise<UniApp.GetBluetoothAdapterStateSuccess> {
    return new Promise((resolve, reject) => {
      uni.getBluetoothAdapterState({
        success: (res) => {
          resolve(res);
        },
        fail: (error) => {
          reject(new Error(`获取蓝牙状态失败: ${error.errMsg}`));
        },
      });
    });
  }

  /**
   * 开始搜索蓝牙设备
   */
  startBluetoothDevicesDiscovery(services?: string[]): Promise<void> {
    return new Promise((resolve, reject) => {
      uni.startBluetoothDevicesDiscovery({
        services,
        allowDuplicatesKey: false,
        interval: 0,
        success: () => {
          this.isScanning = true;
          resolve();
        },
        fail: (error) => {
          reject(new Error(`开始搜索设备失败: ${error.errMsg}`));
        },
      });
    });
  }

  /**
   * 停止搜索蓝牙设备
   */
  stopBluetoothDevicesDiscovery(): Promise<void> {
    return new Promise((resolve, reject) => {
      uni.stopBluetoothDevicesDiscovery({
        success: () => {
          this.isScanning = false;
          resolve();
        },
        fail: (error) => {
          reject(new Error(`停止搜索设备失败: ${error.errMsg}`));
        },
      });
    });
  }

  /**
   * 获取已发现的蓝牙设备
   */
  getBluetoothDevices(): Promise<UniApp.GetBluetoothDevicesSuccess> {
    return new Promise((resolve, reject) => {
      uni.getBluetoothDevices({
        success: (res) => {
          this.devices = res.devices.filter((item) => item.name.includes("NB"));
          resolve({
            ...res,
            devices: this.devices,
          });
        },
        fail: (error) => {
          reject(new Error(`获取设备列表失败: ${error.errMsg}`));
        },
      });
    });
  }

  /**
   * 连接蓝牙低功耗设备
   */
  createBLEConnection(deviceId: string): Promise<void> {
    return new Promise((resolve, reject) => {
      uni.createBLEConnection({
        deviceId,
        success: (res) => {
          console.log(res, "createBLEConnection");
          
          this.connectedDeviceId = deviceId;
          resolve();
        },
        fail: (error) => {
          reject(new Error(`连接设备失败: ${error.errMsg}`));
        },
      });
    });
  }

  /**
   * 断开蓝牙低功耗设备连接
   */
  closeBLEConnection(deviceId?: string): Promise<void> {
    const targetDeviceId = deviceId || this.connectedDeviceId;
    return new Promise((resolve, reject) => {
      uni.closeBLEConnection({
        deviceId: targetDeviceId,
        success: () => {
          if (targetDeviceId === this.connectedDeviceId) {
            this.connectedDeviceId = "";
          }
          resolve();
        },
        fail: (error) => {
          reject(new Error(`断开连接失败: ${error.errMsg}`));
        },
      });
    });
  }

  /**
   * 获取蓝牙设备所有服务
   */
  getBLEDeviceServices(
    deviceId?: string
  ): Promise<UniApp.GetBLEDeviceServicesSuccess> {
    const targetDeviceId = deviceId || this.connectedDeviceId;
    return new Promise((resolve, reject) => {
      uni.getBLEDeviceServices({
        deviceId: targetDeviceId,
        success: (res) => {
          resolve(res);
        },
        fail: (error) => {
          reject(new Error(`获取设备服务失败: ${error.errMsg}`));
        },
      });
    });
  }

  /**
   * 获取蓝牙设备特征值
   */
  getBLEDeviceCharacteristics(
    serviceId: string,
    deviceId?: string
  ): Promise<UniApp.GetBLEDeviceCharacteristicsSuccess> {
    const targetDeviceId = deviceId || this.connectedDeviceId;
    return new Promise((resolve, reject) => {
      uni.getBLEDeviceCharacteristics({
        deviceId: targetDeviceId,
        serviceId,
        success: (res) => {
          resolve(res);
        },
        fail: (error) => {
          reject(new Error(`获取设备特征值失败: ${error.errMsg}`));
        },
      });
    });
  }

  /**
   * 启用蓝牙设备特征值变化时的 notify 功能
   */
  notifyBLECharacteristicValueChange(
    serviceId: string,
    characteristicId: string,
    state: boolean = true,
    deviceId?: string
  ): Promise<void> {
    const targetDeviceId = deviceId || this.connectedDeviceId;
    return new Promise((resolve, reject) => {
      uni.notifyBLECharacteristicValueChange({
        deviceId: targetDeviceId,
        serviceId,
        characteristicId,
        state,
        success: () => {
          console.log("notifyBLECharacteristicValueChange", "success");
          resolve();
        },
        fail: (error) => {
          reject(new Error(`启用特征值变化通知失败: ${error.errMsg}`));
        },
      });
    });
  }

  /**
   * 读取蓝牙设备特征值
   */
  readBLECharacteristicValue(
    serviceId: string,
    characteristicId: string,
    deviceId?: string
  ): Promise<void> {
    const targetDeviceId = deviceId || this.connectedDeviceId;
    return new Promise((resolve, reject) => {
      uni.readBLECharacteristicValue({
        deviceId: targetDeviceId,
        serviceId,
        characteristicId,
        success: () => {
          resolve();
        },
        fail: (error) => {
          reject(new Error(`读取特征值失败: ${error.errMsg}`));
        },
      });
    });
  }

  /**
   * 向蓝牙设备写入数据
   */
  writeBLECharacteristicValue(
    serviceId: string,
    characteristicId: string,
    value: ArrayBuffer,
    deviceId?: string
  ): Promise<void> {
    const targetDeviceId = deviceId || this.connectedDeviceId;
    return new Promise((resolve, reject) => {
      uni.writeBLECharacteristicValue({
        deviceId: targetDeviceId,
        serviceId,
        characteristicId,
        value: value as any,
        writeType: "write",
        success: (res) => {
          console.log(res, "writeBLECharacteristicValue");

          resolve();
        },
        fail: (error) => {
          reject(new Error(`写入数据失败: ${JSON.stringify(error)}`));
          uni.hideLoading();
        },
      });
    });
    // return writeBLE(targetDeviceId, serviceId, characteristicId, value);
  }

  /**
   * 监听蓝牙适配器状态变化事件
   */
  onBluetoothAdapterStateChange(
    callback: (res: UniApp.OnBluetoothAdapterStateChangeResult) => void
  ): void {
    uni.onBluetoothAdapterStateChange(callback);
  }

  /**
   * 监听寻找到新设备的事件
   */
  onBluetoothDeviceFound(
    callback: (res: UniApp.OnBluetoothDeviceFoundResult) => void
  ): void {
    uni.onBluetoothDeviceFound(callback);
  }

  /**
   * 监听蓝牙连接状态变化事件
   */
  onBLEConnectionStateChange(
    callback: (res: UniApp.OnBLEConnectionStateChangeSuccess) => void
  ): void {
    uni.onBLEConnectionStateChange(callback);
  }

  /**
   * 监听蓝牙设备的特征值变化事件
   */
  onBLECharacteristicValueChange(
    callback: (res: UniApp.OnBLECharacteristicValueChangeSuccess) => void
  ): void {
    uni.onBLECharacteristicValueChange(callback);
  }

  /**
   * 移除蓝牙适配器状态变化事件的监听函数
   */
  offBluetoothAdapterStateChange(): void {
    uni.offBluetoothAdapterStateChange();
  }

  /**
   * 移除寻找到新设备事件的监听函数
   */
  offBluetoothDeviceFound(
    callback?: (res: UniApp.OnBluetoothDeviceFoundResult) => void
  ): void {
    uni.offBluetoothDeviceFound();
  }

  /**
   * 移除蓝牙连接状态变化事件的监听函数
   */
  offBLEConnectionStateChange(
    callback?: (res: UniApp.OnBLEConnectionStateChangeSuccess) => void
  ): void {
    uni.offBLEConnectionStateChange(callback);
  }

  /**
   * 移除蓝牙设备特征值变化事件的监听函数
   */
  offBLECharacteristicValueChange(): void {
    uni.offBLECharacteristicValueChange();
  }

  /**
   * 获取当前连接的设备ID
   */
  getConnectedDeviceId(): string {
    return this.connectedDeviceId;
  }

  /**
   * 检查是否已初始化
   */
  getInitialized(): boolean {
    return this.isInitialized;
  }

  /**
   * 发送数据包到蓝牙设备
   * @param serviceId 服务ID
   * @param characteristicId 特征值ID
   * @param packet 数据包（number数组）
   * @param deviceId 设备ID（可选）
   */
  async sendPacket(
    serviceId: string,
    characteristicId: string,
    packet: number[],
    deviceId?: string
  ): Promise<void> {
    // 将 number 数组转换为 ArrayBuffer
    const buffer = new ArrayBuffer(packet.length);
    const view = new Uint8Array(buffer);
    packet.forEach((byte, index) => {
      view[index] = byte;
    });
    await this.writeBLECharacteristicValue(
      serviceId,
      characteristicId,
      buffer,
      deviceId
    );
  }
}
export function ab2hex(buffer: ArrayBuffer) {
  const hexArr = Array.prototype.map.call(
    new Uint8Array(buffer),
    function (bit) {
      return ("00" + bit.toString(16)).slice(-2);
    }
  );
  return hexArr.join("");
}
// 导出单例实例
export const bluetoothManager = BluetoothManager.getInstance();

// =================== 示例 ===================
// const packet = buildPacket(0x02, [1, 0, 0, 0]); // 安装配置指令
// console.log(
//   "发送数据包:",
//   packet.map((b) => b.toString(16).padStart(2, "0")).join(" ")
// );

// const parsed = parsePacket(packet);
// console.log("解析结果:", parsed);
// 分包写入工具
function writeBLE(
  deviceId: string,
  serviceId: string,
  characteristicId: string,
  buffer: ArrayBuffer,
  withResponse = true
): Promise<void> {
  const maxChunk = 20; // 安卓写入单包最大20字节
  let pos = 0;

  return new Promise((resolve, reject) => {
    function writeChunk() {
      if (pos >= buffer.byteLength) {
        resolve();
        return;
      }
      const end = Math.min(pos + maxChunk, buffer.byteLength);
      const chunk = buffer.slice(pos, end);

      uni.writeBLECharacteristicValue({
        deviceId,
        serviceId,
        characteristicId,
        value: chunk as any,
        writeType: withResponse ? "write" : "writeNoResponse", // 关键区别
        success() {
          pos = end;
          // 安卓需要延时，否则连续写会报错
          setTimeout(writeChunk, 30);
        },
        fail(err) {
          reject(err);
        },
      });
    }
    writeChunk();
  });
}
